#pragma once
#include <iostream>
#include <mutex>

namespace ns_singleton
{
    class HeapOnly
    {
    public:
        static HeapOnly* CreateObj()
        {
            return new HeapOnly();
        }

        HeapOnly(const HeapOnly& ho) = delete;
    private:
        HeapOnly(int a = 0) : _a(a)
        {}  
    private:
        int _a;
    };

    class StackOnly
    {
    public:
        static StackOnly CreateObj()
        {
            return StackOnly();
        }

        void* operator new(size_t n) = delete;
        void operator delete(void* so) = delete;
    private:
        StackOnly(int a = 0) : _a(a)
        {}  
    private:
        int _a;
    };

    class A
    {
    public:
        A(int a = 0) : _a(a)
        {}
    public:
        A(const A& aa) = delete;
        A operator=(const A& aa) = delete;
    private:
        int _a;
    };

    class B final
    {
    public:
        B(int a = 0) : _a(a)
        {}
    private:
        int _a;
    };

    // class C : public B
    // {};

    // class singleton
    // {
    // public:
    //     static singleton& GetInstance()
    //     {
    //         return inst;
    //     }
    //     singleton(const singleton& sg) = delete;
    // private:
    //     singleton(int a = 0) : _a(a)
    //     {}
    // private:
    //     int _a;
    //     static singleton inst;
    // };
    // singleton singleton::inst;

    class singleton
    {
    public:
        // static singleton* GetInstance()
        // {
        //     if(nullptr == inst)
        //     {
        //         mtx.lock();
        //         if(nullptr == inst)
        //         {
        //             inst = new singleton();
        //         }
        //         mtx.unlock();
        //     }
        //     return inst;
        // }

        static singleton& GetInstance()
        {
            static singleton inst;
            return inst;
        }
    private:
        singleton(int a = 0) : _a(a)
        {}

        singleton(const singleton& sg) = delete; 
    private:
        int _a;
        //static singleton* inst;
        //static std::mutex mtx;
    };
    //singleton* singleton::inst = nullptr;
    //std::mutex singleton::mtx;
}